package com.decent.manager.config.security.filter;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.decent.common.bo.MessageBean;
import com.decent.common.enums.AuthExceptionEnum;
import com.decent.manager.system.auth.content.LoginContextHandler;
import com.decent.manager.system.auth.service.AuthService;
import com.decent.manager.system.auth.vo.LoginUser;
import com.decent.manager.config.security.SpringSecurityConfig;
import com.decent.manager.config.security.context.LoginContext;
import com.decent.manager.system.util.CommonServletUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * jwt认证
 *
 * @author 张子旭
 * @date 2022/1/30
 */
@Slf4j
public class JwtVerifyFilter extends BasicAuthenticationFilter {
    private final AuthService authService;

    public JwtVerifyFilter(AuthenticationManager authenticationManager, AuthService authService) {
        super(authenticationManager);
        this.authService = authService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        String requestUri = request.getRequestURI();
        requestUri = StrUtil.removePrefix(requestUri, request.getContextPath());
        // 访问路径无需鉴权
        if (CollectionUtil.contains(SpringSecurityConfig.NONE_SECURITY_URL_PATTERNS, requestUri)) {
            chain.doFilter(request, response);
            return;
        }
        // 如果当前请求带了token，判断token时效性，并获取当前登录用户信息
        String token = authService.getTokenFromRequest(request);
        if (StrUtil.isBlank(token)) {
            CommonServletUtil.writeJsonToResponse(response, new MessageBean(AuthExceptionEnum.LOGIN_EXPIRED));
            return;
        }
        LoginUser loginUser = authService.getLoginUserByToken(token);
        // 如果当前登录用户不为空，就设置spring security上下文
        if (!ObjectUtil.isNotNull(loginUser)) {
            CommonServletUtil.writeJsonToResponse(response, new MessageBean(AuthExceptionEnum.LOGIN_EXPIRED));
            return;
        }
        authService.setSpringSecurityContextAuthentication(loginUser);
        // 校验权限
        LoginContext current = LoginContextHandler.current();
        // 如果是超级管理员，直接放过权限校验
        boolean isSuperAdmin = current.isSuperAdmin();
        if (isSuperAdmin) {
            chain.doFilter(request, response);
            return;
        }
        boolean hasUriPermission = LoginContextHandler.current().hasPermission(requestUri);
        if (!hasUriPermission) {
            log.warn("当前账户[{}]无[{}]访问权限", loginUser.getUserAccount(), requestUri);
            CommonServletUtil.writeJsonToResponse(response, MessageBean.fail(AuthExceptionEnum.NO_PERMISSION.getMessage()));
            return;
        }
        chain.doFilter(request, response);
    }
}
